• ivy-maven-plugin-master



package com.github.remisthoughts; import java.io.File; import java.net.URL; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeMap; import org.apache.ivy.Ivy; import org.apache.ivy.core.module.descriptor.Configuration; import org.apache.ivy.core.module.descriptor.DefaultDependencyDescriptor; import org.apache.ivy.core.module.descriptor.DefaultIncludeRule; import org.apache.ivy.core.module.descriptor.DefaultModuleDescriptor; import org.apache.ivy.core.module.descriptor.MDArtifact; import org.apache.ivy.core.module.id.ArtifactId; import org.apache.ivy.core.module.id.ModuleRevisionId; import org.apache.ivy.core.report.ArtifactDownloadReport; import org.apache.ivy.core.report.ResolveReport; import org.apache.ivy.core.resolve.ResolveOptions; import org.apache.ivy.core.settings.IvySettings; import org.apache.ivy.plugins.matcher.ExactOrRegexpPatternMatcher; import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.DefaultArtifact; import org.apache.maven.artifact.handler.DefaultArtifactHandler; import org.apache.maven.artifact.versioning.VersionRange; import org.apache.maven.model.Dependency; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.dependency.fromConfiguration.ArtifactItem; import org.apache.maven.plugins.annotations.Component; import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.project.MavenProject; import org.eclipse.aether.RepositorySystem; import org.eclipse.aether.RepositorySystemSession; import org.eclipse.aether.artifact.ArtifactProperties; import org.eclipse.aether.impl.ArtifactResolver; import org.eclipse.aether.internal.impl.DefaultRepositorySystem; import org.eclipse.aether.resolution.ArtifactRequest; import org.eclipse.aether.resolution.ArtifactResolutionException; import org.eclipse.aether.resolution.ArtifactResult; /** * Goal which adds ivy artifacts as dependencies */ @Mojo(name = "ivy", defaultPhase = LifecyclePhase.INITIALIZE) public class IvyMojo extends AbstractMojo { private static final String IVY_GROUP_MARKER = "ivy."; private static final String IVY_CONFIGURATION_MARKER = "."; private static final String CONF = "default"; private class IvyArtifactResolver implements ArtifactResolver { private final Ivy ivy; private final ArtifactResolver delegate; IvyArtifactResolver(Ivy ivy, ArtifactResolver delegate) { this.ivy = ivy; this.delegate = delegate; } public ArtifactResult resolveArtifact(RepositorySystemSession session, ArtifactRequest request) throws ArtifactResolutionException { if (request.getArtifact().getGroupId().startsWith(IVY_GROUP_MARKER)) { return convert(request, retrieve(request).get(0)); } else { return delegate.resolveArtifact(session, request); } } private List<Artifact> retrieve(ArtifactRequest request) throws ArtifactResolutionException { try { String groupId = request.getArtifact().getGroupId().substring(IVY_GROUP_MARKER.length()); return new ArrayList<Artifact>(resolve( ivy, groupId.substring(groupId.indexOf(IVY_CONFIGURATION_MARKER) + 1), request.getArtifact().getArtifactId(), request.getArtifact().getVersion(), request.getArtifact().getClassifier(), request.getArtifact().getExtension(), false, // not transitive, as this is for a single request groupId.substring(0, groupId.indexOf(IVY_CONFIGURATION_MARKER)))); } catch (MojoExecutionException e) { throw new ArtifactResolutionException(Collections.singletonList(new ArtifactResult(request))); } } private ArtifactResult convert(ArtifactRequest request, Artifact mvnArtifact) { Map<String, String> props = new TreeMap<String, String>(); props.put(ArtifactProperties.LANGUAGE, "java"); props.put(ArtifactProperties.TYPE, mvnArtifact.getType()); props.put(ArtifactProperties.CONSTITUTES_BUILD_PATH, "true"); props.put(ArtifactProperties.INCLUDES_DEPENDENCIES, "false"); return new ArtifactResult(request). setArtifact(new org.eclipse.aether.artifact.DefaultArtifact( mvnArtifact.getGroupId(), mvnArtifact.getArtifactId(), mvnArtifact.getClassifier(), mvnArtifact.getType(), mvnArtifact.getVersion()) .setFile(mvnArtifact.getFile()) .setProperties(props)); } public List<ArtifactResult> resolveArtifacts(RepositorySystemSession session, Collection<? extends ArtifactRequest> requests) throws ArtifactResolutionException { List<ArtifactResult> ret = new ArrayList<ArtifactResult>(requests.size()); Collection<ArtifactRequest> delegateRequests = new ArrayList<ArtifactRequest>(requests.size()); for (ArtifactRequest request : requests) { if (request.getArtifact().getGroupId().startsWith(IVY_GROUP_MARKER)) { for (Artifact mvnArtifact : retrieve(request)) { ret.add(convert(request, mvnArtifact)); } } else { delegateRequests.add(request); } } ret.addAll(delegate.resolveArtifacts(session, delegateRequests)); return ret; } } /** * the project */ @Parameter(required = true, defaultValue = "${project}") public MavenProject project; /** * A file or a URL of the Ivy settings. */ @Parameter(property = "settings", required = true) public String settings; /** * Should we get dependencies of the dependencies? */ @Parameter(property = "transitive", defaultValue = "false", required = false) public boolean transitive; /** * Multiple Maven-style {@code <dependencies>}. */ @Parameter(required = true) public ArtifactItem[] dependencies; /** * What scope to add it to */ @Parameter(property = "scope", defaultValue = "compile", required = false) public String scope; @Component public RepositorySystem repoSystem; @Component public ArtifactResolver artifactResolver; public void execute() throws MojoExecutionException { IvySettings settings = new IvySettings(); try { File settingsFile = new File(this.settings); if (settingsFile.exists()) { settings.load(settingsFile); } else { // maybe a URL? settings.load(new URL(this.settings)); } } catch (Exception e) { throw new MojoExecutionException("couldn't load ivy settings from '" + this.settings + "'", e); } Ivy ivy = Ivy.newInstance(settings); for (ArtifactItem item : dependencies) { // we need to resolve now to calculate the transitive // dependencies (if required) Set<Artifact> allResolved = resolve( ivy, item.getGroupId(), item.getArtifactId(), item.getVersion(), item.getClassifier(), item.getType(), transitive, item.getBaseVersion()); for (Artifact resolved : allResolved) { Dependency dep = new Dependency(); dep.setGroupId(resolved.getGroupId()); dep.setArtifactId(resolved.getArtifactId()); dep.setScope(scope); dep.setClassifier(resolved.getClassifier()); dep.setOptional(false); dep.setType(resolved.getType()); dep.setVersion(resolved.getVersion()); project.getModel().addDependency(dep); } } // force a re-calc of the dependencies so maven picks up our new ones project.setDependencyArtifacts(null); ((DefaultRepositorySystem) repoSystem).setArtifactResolver(new IvyArtifactResolver(ivy, artifactResolver)); } private Set<Artifact> resolve( Ivy ivy, String groupId, String artifactId, String version, String classifier, String type, boolean transitive, String configuration // or NULL for "*" ) throws MojoExecutionException { DefaultModuleDescriptor md = DefaultModuleDescriptor.newDefaultInstance(ModuleRevisionId.newInstance("maven-ivy-plugin", "resolution", "1.0")); md.addConfiguration(new Configuration(CONF)); // add our single dependency ModuleRevisionId module = ModuleRevisionId.newInstance(groupId, artifactId, version); DefaultDependencyDescriptor dd = new DefaultDependencyDescriptor(md, module, true, false, transitive); dd.addDependencyConfiguration(CONF, configuration == null ? "*" : configuration); dd.addIncludeRule("", new DefaultIncludeRule( new ArtifactId(module.getModuleId(), classifier == null ? ".*" : classifier, type, type), new ExactOrRegexpPatternMatcher(), Collections.emptyMap())); md.addDependency(dd); ResolveOptions options = new ResolveOptions(); options.setConfs(new String[] { CONF }); options.setLog("default"); options.setUseCacheOnly(false); ResolveReport report = null; try { report = ivy.resolve(md, options); } catch (Exception e) { throw new MojoExecutionException("couldn't load ivy artifact", e); } if (report.getAllArtifactsReports() == null) { throw new MojoExecutionException("no ivy artifacts resolved for artifact"); } // we'll put the artifacts in a Set so if we get duplicates (e.g. from different configurations) // we'll only process them once. Set<Artifact> artifacts = new HashSet<Artifact>(1); for (ArtifactDownloadReport artifactReport : report.getAllArtifactsReports()) { ModuleRevisionId id = ((MDArtifact) artifactReport.getArtifact()).getModuleRevisionId(); if (artifactReport.getArtifactOrigin() != null && artifactReport.getArtifactOrigin().getArtifact() != null && artifactReport.getArtifactOrigin().getArtifact().getName() != null && artifactReport.getLocalFile() != null) { String thisClassifier = artifactReport.getArtifactOrigin().getArtifact().getName(); String filename = artifactReport.getLocalFile().getName(); String thisType = filename.substring(filename.lastIndexOf('.') + 1); // if there's more than one configuration possible we can't just pick one at // random (!) as it may be private. String thisConfiguration = "*"; if(type != null && !thisType.equals(type)) { continue; } if(classifier != null && !classifier.matches(thisClassifier)) { continue; } DefaultArtifactHandler handler = new DefaultArtifactHandler(); handler.setAddedToClasspath(true); DefaultArtifact artifact = new DefaultArtifact( IVY_GROUP_MARKER + thisConfiguration + IVY_CONFIGURATION_MARKER + id.getOrganisation(), id.getName(), VersionRange.createFromVersion(id.getRevision()), scope, thisType, thisClassifier, handler, false); artifact.setFile(artifactReport.getLocalFile()); artifact.setResolved(true); artifacts.add(artifact); } } if (artifacts.isEmpty()) { throw new MojoExecutionException(String.format("No artifacts resolved")); } else if (!transitive && artifacts.size() > 1) { throw new MojoExecutionException(String.format("Multiple artifacts resolved - %s consider adding <classifier>", artifacts)); } return artifacts; } }